package com.jichangxiu.common.utils;

import cn.hutool.core.util.IdUtil;
import cn.hutool.json.JSONUtil;
import com.jichangxiu.common.entity.bo.Payload;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jws;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.joda.time.DateTime;

import java.math.BigDecimal;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.util.Date;

public class JwtUtils {

    public static final String PAYLOAD_KEY = "Jcx-Boot:User";

    // 创建短令牌
    public static String createJti() {
        return IdUtil.simpleUUID();
    }

    // 私钥加密
    public static String createJwtExpireInMinutes(Object userInfo, PrivateKey privateKey, Long expire) {
        return createJwtExpireInSeconds(userInfo, privateKey, expire * 60);
    }

    // 私钥加密
    public static String createJwtExpireInSeconds(Object userInfo, PrivateKey privateKey, Long expire) {
        return createJwtExpireInSeconds(userInfo, createJti(), privateKey, expire);
    }

    // 私钥加密
    public static String createJwtExpireInSeconds(Object userInfo, String jti, PrivateKey privateKey, Long expire) {
        return Jwts.builder().claim(PAYLOAD_KEY, JSONUtil.toJsonStr(userInfo))
                .setId(jti)
                .setExpiration(DateTime.now().plusSeconds(new BigDecimal(expire).intValue()).toDate())
                .signWith(privateKey, SignatureAlgorithm.RS256).compact();
    }

    // 公钥解析 jwt
    private static Jws<Claims> parserJwt(String jwt, PublicKey publicKey) {
        return Jwts.parser().setSigningKey(publicKey).parseClaimsJws(jwt);
    }

    // 获取 jwt 中的用户信息
    public static <T> Payload<T> getUserInfoFromJwt(String jwt, PublicKey publicKey, Class<T> userType) {
        Jws<Claims> claimsJws = parserJwt(jwt, publicKey);
        Claims body = claimsJws.getBody();
        Payload<T> payload = new Payload<>();
        payload.setJti(body.getId());
        payload.setJwt(jwt);
        String jsonStr = body.get(PAYLOAD_KEY).toString();
        if (JSONUtil.isTypeJSON(jsonStr))
            payload.setUserInfo(JSONUtil.toBean(jsonStr, userType));
        else
            payload.setUserInfo((T) body.get(PAYLOAD_KEY));
        payload.setExpiration(body.getExpiration());
        return payload;
    }

    // 获取 jwt 中的载荷信息
    public static <T> Payload<T> getUserInfoFromJwt(String jwt, PublicKey publicKey) {
        Jws<Claims> claimsJws = parserJwt(jwt, publicKey);
        Claims body = claimsJws.getBody();
        Payload<T> payload = new Payload<>();
        payload.setJti(body.getId());
        payload.setJwt(jwt);
        payload.setExpiration(body.getExpiration());
        payload.setUserInfo((T) body.get(PAYLOAD_KEY));
        return payload;
    }

    // 判断 jwt 是否过期
    public static boolean jwtIsExpired(Date expiration) {
        return expiration.before(new Date());
    }

}
